package com.wave.gate.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import com.alibaba.fastjson2.JSON;
import com.wave.gate.constant.CommonConstants;
import com.wave.gate.domain.PassRecord;
import com.wave.gate.init.InitBaseInfo;
import com.wave.gate.service.IPassRecordService;
import com.wave.gate.util.GuavaCache;
import com.wave.gate.util.HttpUtils;
import com.wave.gate.util.NorcoAPIUtil;
import com.wave.gate.mqtt.client.MqttSendClient;
import com.wave.gate.util.PingUtil;
import com.wave.gate.vo.GatePassSetVo;
import com.wave.gate.vo.GatePassWeightParamVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author TanLei
 * @className：DeviceHeartTask
 * @description：TODO
 * @date 2023/5/9 12:00
 * @version: 1.0
 */
@Component
@Slf4j
public class DeviceHeartbeatTask {

    @Value("${wave.door.security.http}")
    private String http;

    @Value("${electronicBalance.mobile.error}")
    private Double mobileError;

    @Value("${electronicBalance.token.error}")
    private Double tokenError;

    @Autowired
    IPassRecordService passRecordService;

    @Value("${electronicBalance.index}")
    public int electronicBalanceIndex;

    /**
     * 每分钟发送http请求更新下该套设备的ip集合/手机、token重量误差集合缓存
     * @throws Exception
     */
    @Scheduled(cron = "0 */1 * * * ?")
    public void getManageCache(){
        try {
            int queryIps = 1;
            int queryWeight = 1;
            GatePassSetVo passsetipInfo = GuavaCache.PASSSET_CACHE.getIfPresent("passsetipInfo");
            List<GatePassWeightParamVo> mobileTokenweightList = GuavaCache.MOBILE_TOKEN_WEIGHTLIST_CACHE.getIfPresent("mobileTokenweightList");
            if(null==passsetipInfo ){
                queryIps = 2;
            }
            if(CollectionUtils.isEmpty(mobileTokenweightList)){
                queryWeight = 2;
            }
            String url = http + "/wave-gate/device/cache";
            //设置请求参数   前后端约定通过json格式传递参数，此时就不能用form方法了，改用它提供的body方法
            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("deviceIP", InitBaseInfo.ipAddress);
            paramsMap.put("queryIps", queryIps);
            paramsMap.put("queryWeight", queryWeight);
            paramsMap.put("mobileError", mobileError);
            paramsMap.put("tokenError", tokenError);
            HttpResponse execute = HttpUtils.httpCache(url, paramsMap);
            String body = execute.body();   // 获取响应主体
            if(execute.isOk()){
                Map<String, String> map = JSON.parseObject(body, HashMap.class);
                if("200".equals(map.get("code"))){
                    if(queryIps == 2){
                        GuavaCache.PASSSET_CACHE.put("passsetipInfo", JSON.parseObject(map.get("passsetipInfo"), GatePassSetVo.class));
                    }
                    if(queryWeight == 2){
                        GuavaCache.MOBILE_TOKEN_WEIGHTLIST_CACHE.put("mobileTokenweightList",
                                JSON.parseArray(map.get("mobileTokenweightList"), GatePassWeightParamVo.class));
                    }

                }
            }
            if(!execute.isOk()){
                log.info("每分钟发送到后台的更新该套设备的ip集合/手机、token重量误差集合缓存http请求失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("每分钟发送到后台的更新该套设备的ip集合/手机、token重量误差集合缓存http请求失败");
        }

    }

    /**
     * 每分钟发送到后台更新设备在线状态的http请求
     * @throws Exception
     */
    @Scheduled(cron = "0 */1 * * * ?")
    public void checkNetIsUnblocked(){
        try {
            GatePassSetVo gatePassSet = GuavaCache.PASSSET_CACHE.getIfPresent("passsetipInfo");
            if(null == gatePassSet){
                return;
            }
            Set<String> onlineIps = new HashSet<>();
            Set<String> offlineIps = new HashSet<>();

            String deviceIp = gatePassSet.getDeviceIp();
            String pclIp = gatePassSet.getPclIp();
            String inFaceIp = gatePassSet.getInFaceIp();
            String inGateIp = gatePassSet.getInGateIp();
            String inCameraIp = gatePassSet.getInCameraIp();
            String inMiddleCameraIp = gatePassSet.getInMiddleCameraIp();
            String outFaceIp = gatePassSet.getOutFaceIp();
            String outGateIp = gatePassSet.getOutGateIp();
            String outCameraIp = gatePassSet.getOutCameraIp();
            String outMiddleCameraIp = gatePassSet.getOutMiddleCameraIp();

            onlineIps.add(deviceIp);
            boolean b = PingUtil.ping(pclIp) ? onlineIps.add(pclIp) : offlineIps.add(pclIp);
            b = PingUtil.ping(inFaceIp) ? onlineIps.add(inFaceIp) : offlineIps.add(inFaceIp);
            b = PingUtil.ping(inGateIp) ? onlineIps.add(inGateIp) : offlineIps.add(inGateIp);
            b = PingUtil.ping(inCameraIp) ? onlineIps.add(inCameraIp) : offlineIps.add(inCameraIp);
            b = PingUtil.ping(inMiddleCameraIp) ? onlineIps.add(inMiddleCameraIp) : offlineIps.add(inMiddleCameraIp);
            b = PingUtil.ping(outFaceIp) ? onlineIps.add(outFaceIp) : offlineIps.add(outFaceIp);
            b = PingUtil.ping(outGateIp) ? onlineIps.add(outGateIp) : offlineIps.add(outGateIp);
            b = PingUtil.ping(outCameraIp) ? onlineIps.add(outCameraIp) : offlineIps.add(outCameraIp);
            b = PingUtil.ping(outMiddleCameraIp) ? onlineIps.add(outMiddleCameraIp) : offlineIps.add(outMiddleCameraIp);

            String url = http + "/wave-gate/device/heartbeat";
            //设置请求参数   前后端约定通过json格式传递参数，此时就不能用form方法了，改用它提供的body方法
            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("deviceIP", deviceIp);
            paramsMap.put("onlineIps", String.join(",", onlineIps));
            paramsMap.put("offlineIps", String.join(",", offlineIps));
            HttpResponse execute = HttpUtils.httpCache(url, paramsMap);
            String body = execute.body();   // 获取响应主体
            if(!execute.isOk()){
                log.info("每分钟发送到后台更新设备在线状态的http请求失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("每分钟发送到后台更新设备在线状态的http请求失败");
        }

    }

    /**
     * 每小时执行任务
     */
    @Scheduled(cron = "0 0 */1 * * ?")
    public void uploadData(){
        try {
            List<PassRecord> list = passRecordService.list();
            if(CollectionUtils.isEmpty(list)){
                return;
            }
            String url = http + "/wave-gate/device/uploadData";
            //设置请求参数   前后端约定通过json格式传递参数，此时就不能用form方法了，改用它提供的body方法
            Map<String, Object> paramsMap = new HashMap<>();
            List<String> collect = list.stream().map(PassRecord::getPassRecordJson).collect(Collectors.toList());
            paramsMap.put("gatePassRecordDTOList", collect);
            HttpResponse execute = HttpUtils.httpCache(url, paramsMap);
            String body = execute.body();   // 获取响应主体
            if(execute.isOk()){
                Map<String, String> map = JSON.parseObject(body, HashMap.class);
                if("200".equals(map.get("code"))){
                    passRecordService.getBaseMapper().delete(null);
                }
            }
            if(!execute.isOk()){
                log.info("每小时执行任务，上传通行记录http请求失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("每小时执行任务，上传通行记录http请求失败");
        }

    }

    /**
     * 定时电子秤清零,每天5.40,10.40,15.40,23.40
     */
    @Scheduled(cron = "0 40 5,10,16,23 * * ?")
    public void balanceZero(){
        try {
            Set<Double> deviceWeightData1 = NorcoAPIUtil.getDeviceWeightData(1);
            if(CollectionUtils.isEmpty(deviceWeightData1)){
                log.info("定时任务电子秤1清零，重量为空,进行清零操作");
                String zeroorder = CommonConstants.ZEROORDER1_1;
                if(electronicBalanceIndex == 2){
                    zeroorder = CommonConstants.ZEROORDER2_1;
                }
                NorcoAPIUtil.electronicBalanceSendData(CommonConstants.COM_NODE0, zeroorder);
            }
            if(!CollectionUtils.isEmpty(deviceWeightData1)){
                int count1 = 0;
                while (count1 < 20){
                    List<Double> weightList = new ArrayList<>(deviceWeightData1);
                    double max_weight = weightList.get(weightList.size() - 1);
                    if(max_weight <= 10.0){
                        log.info("定时任务电子秤1清零，最大重量为：{},小于等于10g，进行清零操作", max_weight);
                        String zeroorder = CommonConstants.ZEROORDER1_1;
                        if(electronicBalanceIndex == 2){
                            zeroorder = CommonConstants.ZEROORDER2_1;
                        }
                        NorcoAPIUtil.electronicBalanceSendData(CommonConstants.COM_NODE0, zeroorder);
                        break;//如果清零了就退出循环
                    }else {
                        count1 ++;
                        Thread.sleep(10000);
                    }
                }
            }

            Set<Double> deviceWeightData2 = NorcoAPIUtil.getDeviceWeightData(2);
            if(CollectionUtils.isEmpty(deviceWeightData2)){
                log.info("定时任务电子秤2清零，重量为空,进行清零操作");
                String zeroorder = CommonConstants.ZEROORDER1_2;
                if(electronicBalanceIndex == 2){
                    zeroorder = CommonConstants.ZEROORDER2_2;
                }
                NorcoAPIUtil.electronicBalanceSendData(CommonConstants.COM_NODE0, zeroorder);
            }
            if(!CollectionUtils.isEmpty(deviceWeightData2)){
                int count2 = 0;
                while (count2 < 20){
                    List<Double> weightList = new ArrayList<>(deviceWeightData2);
                    double max_weight = weightList.get(weightList.size() - 1);
                    if(max_weight <= 10.0){
                        log.info("定时任务电子秤2清零，最大重量为：{},小于等于10g，进行清零操作", max_weight);
                        String zeroorder = CommonConstants.ZEROORDER1_2;
                        if(electronicBalanceIndex == 2){
                            zeroorder = CommonConstants.ZEROORDER2_2;
                        }
                        NorcoAPIUtil.electronicBalanceSendData(CommonConstants.COM_NODE0, zeroorder);
                        break;//如果清零了就退出循环
                    }else {
                        count2 ++;
                        Thread.sleep(10000);
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            log.info("定时电子秤清零失败");
        }

    }

    //@Scheduled(cron = "*/30 * * * * ?")
    public void getDe() throws InterruptedException, FileNotFoundException {
        Set<Double> deviceWeightData = NorcoAPIUtil.getDeviceWeightData(1);
        PrintWriter pw = new PrintWriter(new FileOutputStream("/home/linaro/waveGate/weight1.txt", true), true);
        pw.println(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss----") + Arrays.toString(deviceWeightData.toArray()));
        pw.close();

        Set<Double> deviceWeightData2 = NorcoAPIUtil.getDeviceWeightData(2);
        PrintWriter pw2 = new PrintWriter(new FileOutputStream("/home/linaro/waveGate/weight2.txt", true), true);
        pw2.println(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss----") + Arrays.toString(deviceWeightData2.toArray()));
        pw2.close();
    }
}

